package com.flowable.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.flowable.common.result.CommonResult;
import com.flowable.pojo.ProcessModel;
import com.flowable.service.ProcModelService;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

/**
 * 流程模型 实现
 */
@Service
public class ProcModelServiceImpl implements ProcModelService {

    /**
     * 转为bpmn.xml，并预览
     *
     * @param processModel json格式
     * @throws IOException
     */
    @Override
    public void json2bpmnxmlAndView(ProcessModel processModel) throws IOException {
        BpmnModel bpmnModel = processModel.toBpmnModel();
        byte[] xmlBytes = new BpmnXMLConverter().convertToXML(bpmnModel);
        if (Objects.nonNull(xmlBytes)) {
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
            String fileName = processModel.getName().replaceAll(" ", "_") + ".bpmn20.xml";
            if (Objects.nonNull(response)) {
                response.setContentType("application/xml");
                response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
                response.setHeader("Content-Disposition", "attachment; filename=file.bpmn20.xml; filename*=" + URLEncoder.encode(fileName, "UTF-8"));
                ServletOutputStream servletOutputStream = response.getOutputStream();
                BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(xmlBytes));
                byte[] buffer = new byte[8096];

                while (true) {
                    int count = in.read(buffer);
                    if (count == -1) {
                        servletOutputStream.flush();
                        servletOutputStream.close();
                        break;
                    }

                    servletOutputStream.write(buffer, 0, count);
                }
            }
        }

    }

    /**
     * 转为bpmn.xml，并上传到/resources目录下
     *
     * @param processModel
     * @return
     */
    @Override
    public CommonResult json2bpmnxmlAndUpload(ProcessModel processModel) {
        JSONObject jsonObject = new JSONObject();
        try {
            BpmnModel bpmnModel = processModel.toBpmnModel();
            byte[] xmlBytes = new BpmnXMLConverter().convertToXML(bpmnModel);
            if (Objects.nonNull(xmlBytes)) {
                String fileName = processModel.getName().replaceAll(" ", "_") + ".bpmn20.xml";
                // 一、target/classes目录
                File targetPath = new File(ResourceUtils.getURL("classpath:").getPath());
                if (!targetPath.exists()) {
                    // 获取当前运行目录
                    targetPath = new File("");
                }
                // 二、resources目录
                String curPath = targetPath.getPath().substring(0, targetPath.getPath().indexOf("target/classes"));
                String resourcesPath = curPath + "src/main/resources";

                FileOutputStream fos0 = new FileOutputStream(targetPath + "/" + fileName);
                FileOutputStream fos1 = new FileOutputStream(resourcesPath + "/" + fileName);
                fos0.write(xmlBytes);
                fos1.write(xmlBytes);
                fos0.close();
                fos1.close();

                BasicFileAttributes attr = Files.readAttributes(Path.of(resourcesPath + "/" + fileName), BasicFileAttributes.class);
                FileTime createTime = attr.creationTime();
                FileTime lastModifiedTime = attr.lastModifiedTime();
                long size = attr.size();
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault());
                jsonObject.put("createTime", formatter.format(createTime.toInstant()));
                jsonObject.put("lastModifiedTime", formatter.format(lastModifiedTime.toInstant()));
                jsonObject.put("filePath", resourcesPath + "/" + fileName);
                jsonObject.put("size", size + " Byte");
            }
        } catch (FileNotFoundException e) {
            return CommonResult.failed(e.getMessage());
        } catch (IOException e) {
            return CommonResult.failed(e.getMessage());
        } catch (Exception e) {
            return CommonResult.failed(e.getMessage());
        }
        return CommonResult.success(jsonObject);
    }
}
